package com.dkd.service.impl;

import cn.elegent.ac.ElegentAC;
import cn.elegent.actx.annotation.ACTransaction;
import cn.elegent.actx.context.ElegentACTXContext;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dkd.config.ACTXConfig;
import com.dkd.config.TopicConfig;
import com.dkd.config.constant.OrderStatus;
import com.dkd.config.constant.PayStatus;
import com.dkd.contract.OrderCheck;
import com.dkd.contract.VendoutContract;
import com.dkd.contract.VendoutData;
import com.dkd.dao.OrderDao;
import com.dkd.entity.OrderEntity;
import com.dkd.exception.LogicException;
import com.dkd.feign.UserService;
import com.dkd.feign.VMService;
import com.dkd.service.OrderService;
import com.dkd.vo.PartnerVO;
import com.dkd.vo.PayVO;
import com.dkd.vo.SkuVO;
import com.dkd.vo.VmVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private VMService vmService;

    @Autowired
    private UserService userService;


    @Autowired(required = false)
    private ElegentAC elegentAC;

    @Override
    public OrderEntity getByOrderNo(String orderNo) {
        QueryWrapper<OrderEntity> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(OrderEntity::getOrderNo,orderNo);
        return this.getOne(qw);
    }


    /**
     * 发货通知
     *
     * @param orderNo   订单没有
     * @param skuId     sku id
     * @param innerCode 内部代码
     * @param amount    量
     * @return boolean
     * @author DiXiaoNie
     * @date 2023/02/05
     */

    @Override
    @ACTransaction(mainName = ACTXConfig.ORDER_VENDOUT, childName = ACTXConfig.ORDER_VENDOUT_PAY)
    public boolean vendout(String orderNo, Long skuId, String innerCode, Integer amount) {
        //封装协议中的数据
        VendoutData vendoutData = new VendoutData();
        vendoutData.setOrderNo(orderNo);
        vendoutData.setSkuId(skuId);
        vendoutData.setAmount(amount);

        //封装协议
        VendoutContract vendoutContract = new VendoutContract();
        vendoutContract.setVendoutData(vendoutData);
        vendoutContract.setInnerCode(innerCode);
        //保存快照
        ElegentACTXContext.setSnapshot("vendoutContract", vendoutContract);
        //向售货机微服务 发送出货请求
        return this.elegentAC.publish(TopicConfig.VMS_VENDOUT_TOPIC, vendoutContract);
    }

    @Override
    public OrderEntity createOrder(PayVO payVO,String platform) {
        if(!vmService.hasCapacity(payVO.getInnerCode()
                ,Long.valueOf(payVO.getSkuId()))){
            throw new LogicException("该商品已售空");
        }
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOpenId(payVO.getOpenId());//openId
        //封装平台名称
        orderEntity.setPayType(platform);
        orderEntity.setPayStatus(PayStatus.PAY_STATUS_NOPAY);//支付状态
        orderEntity.setStatus(OrderStatus.ORDER_STATUS_CREATE);//订单状态
        orderEntity.setOrderNo(payVO.getInnerCode()+System.nanoTime());//订单编号
        //根据售货机编号查询售货机信息 ,并复制给订单对象
        VmVO vm = vmService.getVMInfo(payVO.getInnerCode());
        BeanUtils.copyProperties( vm,orderEntity  );
        orderEntity.setAddr(vm.getNodeAddr());

        //根据商品编号查询商品信息，并复制给订单对象
        SkuVO skuVo = vmService.getSku(payVO.getSkuId());
        BeanUtils.copyProperties( skuVo,orderEntity  );
        orderEntity.setAmount(skuVo.getRealPrice());//价格
        //计算合作商账单分账金额
        PartnerVO partner = userService.getPartner(vm.getOwnerId());

        //如果订单的价格低于10分钱 则不统计分账
        if(skuVo.getRealPrice()<10){
            orderEntity.setBill(0);
        }else {
            BigDecimal bg = new BigDecimal(skuVo.getRealPrice());
            int bill = bg.multiply(new BigDecimal(partner.getRatio())).divide(new BigDecimal(100), 0, RoundingMode.HALF_UP).intValue();
            orderEntity.setBill(bill);
        }
        this.save(orderEntity);

        var orderCheck = new OrderCheck();
        orderCheck.setOrderNo(orderCheck.getOrderNo());
        try {
            this.elegentAC.publish("$delayed/300/" + TopicConfig.ORDER_CHECK_TOPIC, orderCheck);
        } catch (Exception e) {
            log.error("send to emq error", e);
        }

        return orderEntity;
    }

}
